package com.thinvent.workflow.common.util;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.SerializationUtils;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 对象及集合拷贝工具类，基于 Apache Commons BeanUtils 和 SerializationUtils
 */
public final class DataConvertUtils {

    private DataConvertUtils() {
        // 私有构造，禁止实例化
    }

    /**
     * 深度克隆对象（要求实现 Serializable）
     * @param source 源对象
     * @param <T> 类型，必须可序列化
     * @return 深度克隆的新对象
     */
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T deepClone(T source) {
        if (source == null) {
            return null;
        }
        return SerializationUtils.clone(source);
    }

    /**
     * 拷贝属性到目标类型新实例，浅拷贝
     * @param source 源对象
     * @param targetClass 目标类型
     * @param <T> 目标类型
     * @return 新实例
     */
    public static <T> T copy(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        try {
            T target = targetClass.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(target, source);
            return target;
        } catch (Exception e) {
            throw new RuntimeException("DataConvertUtils copy error", e);
        }
    }

    /**
     * 转换列表到指定类型新列表，浅拷贝
     * @param sourceList 源列表
     * @param targetClass 目标类型
     * @param <S> 源类型
     * @param <T> 目标类型
     * @return 新列表
     */
    public static <S, T> List<T> convertList(List<S> sourceList, Class<T> targetClass) {
        if (CollectionUtils.isEmpty(sourceList)) {
            return Collections.emptyList();
        }
        return sourceList.stream()
                .map(src -> copy(src, targetClass))
                .collect(Collectors.toList());
    }

    /**
     * 浅拷贝同类型列表
     * @param sourceList 源列表
     * @param <T> 元素类型
     * @return 新列表
     */
    public static <T> List<T> cloneList(List<T> sourceList) {
        if (CollectionUtils.isEmpty(sourceList)) {
            return Collections.emptyList();
        }
        return sourceList.stream()
                .map(item -> copy(item, (Class<T>) item.getClass()))
                .collect(Collectors.toList());
    }
}
